﻿using Abp.Extensions;
using Microsoft.AspNetCore.Cors.Infrastructure;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace AbpProjectTemplate.Web.Cors
{
    /*
      想要覆盖之前的ICorsService,需要在AddMvc()之后，替换,例如下：
      services.Add(ServiceDescriptor.Transient<ICorsService, WildcardCorsService>());
      services.Configure<CorsOptions>(options => options.AddPolicy(
      "AllowSameDomain",
      builder => builder.WithOrigins("*.test.com")));
       */
    /// <summary>
    /// 自定义跨域处理服务，增加通配符二级域名策略  ICorsService
    /// </summary>
    public class WildcardCorsService : CorsService
    {
        public WildcardCorsService(IOptions<CorsOptions> options, ILoggerFactory loggerFactory)
            : base(options, loggerFactory)
        {

        }

        #region 在默认处理域名策略之前，提前拦截,用自己的策略

        public override void EvaluateRequest(HttpContext context, CorsPolicy policy, CorsResult result)
        {
            var origin = context.Request.Headers[CorsConstants.Origin];
            //拦截
            //Orings为策略(*.test.com)(该策略可多个)    origin为跨域请求的域名
            this.EvaluateOriginForWildcard(policy.Origins, origin);
            //策略根据通配符替换完成
            base.EvaluateRequest(context, policy, result);
        }

        public override void ApplyResult(CorsResult result, HttpResponse response)
        {
            base.ApplyResult(result, response);
        }

        public override void EvaluatePreflightRequest(HttpContext context, CorsPolicy policy, CorsResult result)
        {
            var origin = context.Request.Headers[CorsConstants.Origin];
            //拦截
            this.EvaluateOriginForWildcard(policy.Origins, origin);
            //策略根据通配符替换完成
            base.EvaluatePreflightRequest(context, policy, result);
        }
        #endregion
        private void EvaluateOriginForWildcard(IList<string> origins, string origin)
        {
            //只在没有匹配的origin的情况下进行操作
            if (!origins.Contains(origin))
            {
                if (origins.Any(wildcardDomain => Regex.IsMatch(origin, wildcardDomain)))
                    origins.Add(origin);
            }
        }
    }
}
